home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / pilot-mail.c < prev    next >
C/C++ Source or Header  |  1997-08-11  |  23KB  |  910 lines

  1. /* pilot-mail.c:  Make mail go voom-voom tween da Pilot an da Net
  2.  *
  3.  * Copyright (c) 1997, Kenneth Albanowski
  4.  *
  5.  * This is free software, licensed under the GNU Public License V2.
  6.  * See the file COPYING for details.
  7.  *
  8.  * Modifications by Diego Zamboni to allow it to read mail from an MH-style
  9.  * mailbox into the Pilot.
  10.  *
  11.  */
  12.  
  13. #define PILOTPORT        ""
  14. #define POPHOST         ""
  15. #define POPUSER                ""
  16. #define POPPASS                ""
  17. #define PILOTFROM        ""
  18. #ifdef OS2
  19. #define SENDMAIL        "sendmail -t"
  20. #else
  21. #define SENDMAIL        "/usr/lib/sendmail -t -i"
  22. #endif
  23. #define POPKEEP         "keep"
  24. #define DISPOSE                "keep"
  25. #define TOPILOT_MHDIR   ""
  26.  
  27. /* Todo: truncation, filtering, priority, notification */
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. #include "pi-source.h"
  34. #include "pi-socket.h"
  35. #include "pi-mail.h"
  36. #include "pi-dlp.h"
  37. #include <signal.h>
  38.  
  39. #include <sys/types.h>
  40. #include <sys/socket.h>
  41. #include <netinet/in.h>
  42. #include <arpa/inet.h>
  43. #include <netdb.h>
  44.  
  45. extern time_t parsedate(char * p);
  46.  
  47. void markline(char *msg) {
  48.     while((*msg)!='\n' && (*msg)!=0 ) {
  49.         msg++;
  50.     }
  51.     (*msg)=0;
  52. }
  53.  
  54. int openmhmsg(char *dir, int num) {
  55.     char filename[1000];
  56.  
  57.  
  58.     sprintf(filename, "%s/%d", dir, num);
  59.  
  60.     return open(filename, O_RDONLY);
  61. }
  62.  
  63. /* Fold into RFC822 style*/
  64. void fprintfold(FILE * f, char * t)
  65. {
  66.   while(*t) {
  67.     if ((*t == '\r') || (*t == '\n')) {
  68.       fprintf(f, "\r\n ");
  69.     }
  70.     else {
  71.       putc(*t, f);
  72.     }
  73.     t++;
  74.   }
  75. }
  76.  
  77. /* Translate into sendmail body style */
  78. void fprintbody(FILE * f, char * t)
  79. {
  80.   int c = 1;
  81.   while(*t) {
  82.     if ((*t == '\r') || (*t == '\n')) {
  83.       fprintf(f,"\r\n");
  84.       c = 0;
  85.     }
  86.     else {
  87.       if ((c == 0) && (*t == '.'))
  88.         putc('.', f);
  89.       putc(*t, f);
  90.       c++;
  91.     }
  92.     t++;
  93.   }
  94. }
  95.  
  96. int getpopchar(int socket)
  97. {
  98.   unsigned char buf;
  99.   int l;
  100.   
  101.   do {
  102.     l = read(socket, &buf, 1);
  103.     if (l < 0)
  104.       return l;
  105.   } while ((l==0) || (buf == '\r'));
  106.   
  107.   return buf;
  108. }
  109.  
  110. int getpopstring(int socket, char * buf)
  111. {
  112.   int c;
  113.   while ((c = getpopchar(socket)) >= 0) {
  114.     *buf++ = c;
  115.     if (c == '\n')
  116.       break;
  117.   }
  118.   *buf = '\0';
  119.   return c;
  120. }
  121.  
  122. int getpopresult(int socket, char * buf)
  123. {
  124.   int c = getpopstring(socket, buf);
  125.   
  126.   if (c<0)
  127.     return c;
  128.   
  129.   if (buf[0] == '+')
  130.     return 0;
  131.   else
  132.     return 1;
  133. }
  134.  
  135. char * skipspace(char * c) {
  136.   while (c && ((*c == ' ') || (*c == '\t')))
  137.     c++;
  138.   return c;
  139. }
  140.  
  141. void header(struct Mail * m, char * t)
  142. {
  143.   static char holding[4096];
  144.   
  145.   if (t && strlen(t) && t[strlen(t)-1] == '\n')
  146.     t[strlen(t)-1] = 0;
  147.   
  148.   if (t && ((t[0] == ' ') || (t[0] == '\t'))) {
  149.     if ((strlen(t) + strlen(holding)) > 4096)
  150.       return; /* Just discard approximate overflow */
  151.     strcat(holding, t+1);
  152.     return;
  153.   }
  154.   
  155.   /* Decide on what we do with m->sendTo */
  156.   
  157.   if (strncmp(holding, "From:", 5)==0) {
  158.     m->from = strdup(skipspace(holding+5));
  159.   } else if (strncmp(holding, "To:",3)==0) {
  160.     m->to = strdup(skipspace(holding+3));
  161.   } else if (strncmp(holding, "Subject:",8)==0) {
  162.     m->subject = strdup(skipspace(holding+8));
  163.   } else if (strncmp(holding, "Cc:",3)==0) {
  164.     m->cc = strdup(skipspace(holding+3));
  165.   } else if (strncmp(holding, "Bcc:",4)==0) {
  166.     m->bcc = strdup(skipspace(holding+4));
  167.   } else if (strncmp(holding, "Reply-To:",9)==0) {
  168.     m->replyTo = strdup(skipspace(holding+9));
  169.   } else if (strncmp(holding, "Date:",4)==0) {
  170.     time_t d = parsedate(skipspace(holding+5));
  171.     if (d != -1) {
  172.       struct tm * d2;
  173.       m->dated = 1;
  174.       d2 = localtime(&d);
  175.       m->date = *d2;
  176.     }
  177.   }
  178.   
  179.   holding[0] = 0;
  180.   
  181.   if (t)
  182.     strcpy(holding, t);
  183. }
  184.  
  185.  
  186. void Help(char * progname)
  187. {
  188.   fprintf(stderr,"usage: %s [options]\n",progname);
  189.   fprintf(stderr,"\n      <-p port> Serial port [PILOTPORT]");
  190.   fprintf(stderr,"\n                   (defaults to '%s')", PILOTPORT);
  191.   fprintf(stderr,"\n      <-h host> POP3 host (if empty, mail won't be received) [POPHOST]");
  192.   fprintf(stderr,"\n                   (defaults to '%s')", POPHOST);
  193.   fprintf(stderr,"\n      <-u user> POP3 user name [POPUSER]");
  194.   fprintf(stderr,"\n                   (defaults to '%s')", POPUSER);
  195.   fprintf(stderr,"\n      <-P pass> POP3 password [POPPASS]");
  196.   fprintf(stderr,"\n                   (default value set)");
  197.   fprintf(stderr,"\n      <-f address> Outgoing 'From:' line [PILOTFROM]");
  198.   fprintf(stderr,"\n                   (defaults to '%s')", PILOTFROM);
  199.   fprintf(stderr,"\n      <-s command> Sendmail command (if empty, mail won't be sent) [SENDMAIL]");
  200.   fprintf(stderr,"\n                   (defaults to '%s')", SENDMAIL);
  201.   fprintf(stderr,"\n      <-k keep|delete> Keep mail on POP server [POPKEEP]");
  202.   fprintf(stderr,"\n                   (defaults to '%s')", POPKEEP);
  203.   fprintf(stderr,"\n      <-d keep|delete|file> Disposition of sent mail [PILOTDISPOSE]");
  204.   fprintf(stderr,"\n                   (defaults to '%s')", DISPOSE);
  205.   fprintf(stderr,"\n      <-m mhdir> MH directory to download to Pilot [TOPILOT_MHDIR]");
  206.   fprintf(stderr,"\n                   (defaults to '%s')", TOPILOT_MHDIR);
  207.   fprintf(stderr, "\n\nAll options may be specified via the environment variable named in brackets.\n");
  208.   exit(0);
  209. }
  210.  
  211. void sigint(int num)
  212. {
  213.   *((char*)0)=0;
  214. }
  215.                   
  216. int main(int argc, char *argv[])
  217. {
  218.   struct pi_sockaddr addr;
  219.   int db;
  220.   int sd;
  221.   int i,l;
  222.   int lost,dupe,rec,sent;
  223.   struct PilotUser U;
  224.   int ret;
  225.   unsigned char buffer[0xffff];
  226.   struct MailAppInfo tai;
  227.   struct MailSyncPref p;
  228.   struct MailSignaturePref sig;
  229.   struct sockaddr_in pop_addr;
  230.   int popfd;
  231.   struct hostent * hostent;
  232.   int c;
  233.   char * progname = argv[0];
  234.   
  235.   char * from_address = 
  236. #ifdef PILOTFROM
  237.   PILOTFROM;
  238. #else
  239.   "";
  240. #endif
  241.   char * pop_host = 
  242. #ifdef POPHOST
  243.   POPHOST;
  244. #else
  245.   "";
  246. #endif
  247.   char * pop_user =
  248. #ifdef POPUSER
  249.   POPUSER;
  250. #else
  251.   "";
  252. #endif
  253.   char * pop_pass =
  254. #ifdef POPPASS
  255.   POPPASS;
  256. #else
  257.   "";
  258. #endif
  259.   char * sendmail =
  260. #ifdef SENDMAIL
  261.   SENDMAIL;
  262. #else
  263.   "";
  264. #endif
  265.   char * pop_keep =
  266. #ifdef POPKEEP
  267.   POPKEEP;
  268. #else
  269.   "";
  270. #endif
  271.   char * dispose =
  272. #ifdef DISPOSE
  273.   DISPOSE;
  274. #else
  275.   "";
  276. #endif
  277.   char * port =
  278. #ifdef PILOTPORT
  279.   PILOTPORT;
  280. #else
  281.   "";
  282. #endif
  283.   char * mh_dir =
  284. #ifdef TOPILOT_MHDIR
  285.   TOPILOT_MHDIR;
  286. #else
  287.   "";
  288. #endif
  289.  
  290.   extern char* optarg;
  291.   extern int optind;
  292.   
  293.  
  294.   if (getenv("SENDMAIL"))
  295.     sendmail = getenv("SENDMAIL");
  296.   if (getenv("POPKEEP"))
  297.     pop_keep = getenv("POPKEEP");
  298.   if (getenv("PILOTDISPOSE"))
  299.     dispose = getenv("PILOTDISPOSE");
  300.   if (getenv("PILOTFROM"))
  301.     from_address = getenv("PILOTFROM");
  302.   if (getenv("POPHOST"))
  303.     pop_host = getenv("POPHOST");
  304.   if (getenv("POPUSER"))
  305.     pop_user = getenv("POPUSER");
  306.   if (getenv("POPPASS"))
  307.     pop_pass = getenv("POPPASS");
  308.   if (getenv("PILOTPORT"))
  309.     port = getenv("PILOTPORT");
  310.   if (getenv("TOPILOT_MHDIR"))
  311.     mh_dir = getenv("TOPILOT_MHDIR");
  312.      
  313.   signal(SIGINT, sigint);
  314.  
  315.   while ((c = getopt(argc, argv, "s:p:d:f:h:u:p:h:P:k:m:")) != EOF) {
  316.     switch (c) {
  317.       case 's':
  318.         sendmail = optarg;
  319.         break;
  320.       case 'p':
  321.         port = optarg;
  322.         break;
  323.       case 'h':
  324.         pop_host = optarg;
  325.         break;
  326.       case 'u':
  327.         pop_user = optarg;
  328.         break;
  329.       case 'P':
  330.         pop_pass = optarg;
  331.         break;
  332.       case 'f':
  333.         from_address = optarg;
  334.         break;
  335.       case 'd':
  336.         dispose = optarg;
  337.         break;
  338.       case 'k':
  339.         pop_keep = optarg;
  340.         break;
  341.       case 'm':
  342.         mh_dir = optarg;
  343.         break;
  344.       case 'H': case '?': default:
  345.         Help(progname);
  346.     }
  347.   }
  348.   argc -= optind;
  349.   argv += optind;
  350.   
  351.   if (!strlen(port)) {
  352.     fprintf(stderr, "Port must be set.\n\n");
  353.     Help(progname);
  354.   }
  355.   
  356.   
  357.   if (!strlen(pop_host) && !strlen(sendmail)) {
  358.     fprintf(stderr, "At least one of -h or -s must be set.\n\n");
  359.     Help(progname);
  360.   }
  361.   
  362.   if (strlen(pop_host)) {
  363.     if (!strlen(pop_user)) {
  364.       fprintf(stderr, "-u must be set to receive mail.\n\n");
  365.       Help(progname);
  366.     } else if (!strlen(pop_keep) || (strcmp(pop_keep, "keep") && strcmp(pop_keep,"delete"))) {
  367.       fprintf(stderr, "-k must have an argument of 'keep' or 'delete'.\n\n");
  368.       Help(progname);
  369.     } 
  370.   }
  371.  
  372.   if ( !strlen( pop_pass ) && strlen( pop_host ) )
  373.     {
  374.       pop_pass = getpass( "POP password: " );
  375.     }
  376.   
  377.   if (strlen(sendmail)) {
  378.     if (!strlen(dispose) || (strcmp(dispose,"keep") &&
  379.                              strcmp(dispose,"delete") &&
  380.                              strcmp(dispose,"file"))) {
  381.       fprintf(stderr, "-d must have an argument of 'keep', 'delete', or 'file'.\n\n");
  382.       Help(progname);
  383.     }
  384.   }
  385.   
  386.   if (!(sd = pi_socket(PI_AF_SLP, PI_SOCK_STREAM, PI_PF_PADP))) {
  387.     perror("pi_socket");
  388.     exit(1);
  389.   }
  390.   
  391.   lost = dupe = rec = sent = 0;
  392.   
  393.   addr.pi_family = PI_AF_SLP;
  394.   strcpy(addr.pi_device, port);
  395.   
  396.   ret = pi_bind(sd, (struct sockaddr*)&addr, sizeof(addr));
  397.   if(ret == -1) {
  398.     perror("pi_bind");
  399.     exit(1);
  400.   }
  401.  
  402.   ret = pi_listen(sd,1);
  403.   if(ret == -1) {
  404.     perror("pi_listen");
  405.     exit(1);
  406.   }
  407.  
  408.   sd = pi_accept(sd, 0, 0);
  409.   if(sd == -1) {
  410.     perror("pi_accept");
  411.     exit(1);
  412.   }
  413.   
  414.   memset(&tai, '\0', sizeof(struct MailAppInfo));
  415.   memset(&p, '\0', sizeof(struct MailSyncPref));
  416.  
  417.   /* Ask the pilot who it is. */
  418.   dlp_ReadUserInfo(sd,&U);
  419.   
  420.   /* Tell user (via Pilot) that we are starting things up */
  421.   dlp_OpenConduit(sd);
  422.   
  423.   /* Open the Mail database, store access handle in db */
  424.   if(dlp_OpenDB(sd, 0, 0x80|0x40, "MailDB", &db) < 0) {
  425.     fprintf(stderr, "Unable to open MailDB\n");
  426.     dlp_AddSyncLogEntry(sd, "Unable to open MailDB.\n");
  427.     exit(1);
  428.   }
  429.   
  430.   dlp_ReadAppBlock(sd, db, 0, buffer, 0xffff);
  431.   unpack_MailAppInfo(&tai, buffer, 0xffff);
  432.   
  433.   setbuf(stderr, 0);
  434.   
  435.   p.syncType = 0;
  436.   p.getHigh = 0;
  437.   p.getContaining = 0;
  438.   p.truncate = 8*1024;
  439.   p.filterTo = 0;
  440.   p.filterFrom = 0;
  441.   p.filterSubject = 0;
  442.   
  443.   if (pi_version(sd) > 0x0100) {
  444.     if (dlp_ReadAppPreference(sd, makelong("mail"), 1, 1, 0xffff, buffer, 0, 0)>=0) {
  445.       printf("Got local backup mail preferences\n"); /* 2 for remote prefs */
  446.       unpack_MailSyncPref(&p, buffer, 0xffff);
  447.     } else {
  448.       printf("Unable to get mail preferences, trying current\n");
  449.       if (dlp_ReadAppPreference(sd, makelong("mail"), 1, 1, 0xffff, buffer, 0, 0)>=0) {
  450.         printf("Got local current mail preferences\n"); /* 2 for remote prefs */
  451.         unpack_MailSyncPref(&p, buffer, 0xffff);
  452.       } else
  453.         printf("Couldn't get any mail preferences.\n");
  454.     }
  455.     
  456.     if (dlp_ReadAppPreference(sd, makelong("mail"), 3, 1, 0xffff, buffer, 0, 0)>0) {
  457.       unpack_MailSignaturePref(&sig, buffer, 0xffff);
  458.     }
  459.  
  460.   }
  461.  
  462.   printf("Local Prefs: Sync=%d, High=%d, getc=%d, trunc=%d, to=|%s|, from=|%s|, subj=|%s|\n",
  463.      p.syncType, p.getHigh, p.getContaining, p.truncate, p.filterTo ? p.filterTo : "<none>",
  464.      p.filterFrom ? p.filterFrom : "<none>", p.filterSubject ? p.filterSubject : "<none>");
  465.  
  466.   printf("AppInfo Signature: |%s|\n\n", sig.signature ? sig.signature : "<None>");
  467.  
  468. #if 0
  469.   for (i=0;1;i++) {
  470.           struct Mail t;
  471.           int attr, category;
  472.                                      
  473.           int len = dlp_ReadRecordByIndex(sd, db, i, buffer, 0, 0, &attr, &category);
  474.           if(len<0)
  475.                   break;
  476.                   
  477.           /* Skip deleted records */
  478.           if((attr & dlpRecAttrDeleted) || (attr & dlpRecAttrArchived))
  479.                   continue;
  480.                   
  481.         unpack_Mail(&t, buffer, len);
  482.         
  483.         printf("Category: %s\n", tai.CategoryName[category]);
  484.         printf("Read: %d, Signature: %d, confirmRead: %d, confirmDeliver: %d, priority: %d, address: %d\n",
  485.                t.read, t.signature, t.confirmRead, t.confirmDelivery, t.priority, t.addressing);
  486.         printf("Time: %s", t.dated ? asctime(&t.date) : "<Undated>");
  487.         printf("Subject: |%s|\n", t.subject ? t.subject : "<None>");
  488.         printf("From: |%s|\n", t.from ? t.from : "<None>");
  489.         printf("To: |%s|\n", t.to ? t.to : "<None>");
  490.         printf("Cc: |%s|\n", t.cc ? t.cc : "<None>");
  491.         printf("Bcc: |%s|\n", t.bcc ? t.bcc : "<None>");
  492.         printf("ReplyTo: |%s|\n", t.replyTo ? t.replyTo : "<None>");
  493.         printf("SendTo: |%s|\n", t.sentTo ? t.sentTo : "<None>");
  494.         printf("Body: |%s|\n", t.body ? t.body : "<None>");
  495.         printf("\n");
  496.  
  497.         free_Mail(&t);
  498.   }
  499. #endif
  500.  
  501.   if (strlen(sendmail)) {
  502.   /* sendmail transmission section */
  503.  
  504.   /* Iterate over messages in Outbox */
  505.   for (i=0;1;i++) {
  506.           struct Mail t;
  507.           int attr;
  508.           int size;
  509.           recordid_t id;
  510.           FILE * sendf;
  511.                                      
  512.           int len = dlp_ReadNextRecInCategory(sd, db, 1, buffer, &id, 0, &size, &attr);
  513.           if(len<0)
  514.                   break;
  515.                   
  516.           /* Skip deleted records */
  517.           if((attr & dlpRecAttrDeleted) || (attr & dlpRecAttrArchived))
  518.                   continue;
  519.                   
  520.         unpack_Mail(&t, buffer, len);
  521.  
  522.           sendf = popen(sendmail, "w");
  523.           
  524.           if (!sendf) {
  525.             fprintf(stderr,"Error launching '%s' to transmit mail! (No mail lost, %d received, %d sent)\n",
  526.                     sendmail, rec, sent);
  527.             pi_close(sd);
  528.             exit(1);
  529.           }
  530.         
  531.         if (from_address) {
  532.           fprintf(sendf,"From: ");
  533.           fprintf(sendf, from_address);
  534.           fprintf(sendf,"\r\n");
  535.         }
  536.  
  537.         if (t.to) {
  538.           fprintf(sendf,"To: ");
  539.           fprintfold(sendf,t.to);
  540.           fprintf(sendf,"\r\n");
  541.         }
  542.         if (t.cc) {
  543.           fprintf(sendf,"Cc: ");
  544.           fprintfold(sendf,t.cc);
  545.           fprintf(sendf,"\r\n");
  546.         }
  547.         if (t.bcc) {
  548.           fprintf(sendf,"Bcc: ");
  549.           fprintfold(sendf,t.bcc);
  550.           fprintf(sendf,"\r\n");
  551.         }
  552.         if (t.replyTo) {
  553.           fprintf(sendf,"Reply-To: ");
  554.           fprintfold(sendf,t.replyTo);
  555.           fprintf(sendf,"\r\n");
  556.         }
  557.         if (t.subject) {
  558.           fprintf(sendf,"Subject: ");
  559.           fprintfold(sendf,t.subject);
  560.           fprintf(sendf,"\r\n");
  561.         }
  562.         fprintf(sendf, "X-mailer: pilot-mail-%d.%d.%d\r\n", PILOT_LINK_VERSION,PILOT_LINK_MAJOR,PILOT_LINK_MINOR);
  563.         fprintf(sendf,"\r\n"); /* Separate header */
  564.         
  565.         if (t.body) {
  566.           fprintbody(sendf,t.body);
  567.           fprintf(sendf,"\r\n");
  568.         }
  569.         if (t.signature && sig.signature) {
  570.           char * c = sig.signature;
  571.           while ((*c == '\r') || (*c == '\n'))
  572.                   c++;
  573.           if(
  574.              strncmp(c,"--",2) &&
  575.              strncmp(c,"__",2)
  576.             ) {
  577.             fprintf(sendf,"\r\n-- \r\n");
  578.           }
  579.           fprintbody(sendf,sig.signature);
  580.           fprintf(sendf,"\r\n");
  581.         }
  582.  
  583.         if (pclose(sendf) == 0) {
  584.           sent++;
  585.           if (strcmp(dispose,"keep")==0) {
  586.             dupe++;
  587.           } else if (strcmp(dispose,"delete")==0) {
  588.             dlp_DeleteRecord(sd, db, 0, id);
  589.           } else {
  590.             /* Rewrite into Filed category */
  591.             dlp_WriteRecord(sd, db, attr, id, 3, buffer, size, 0);
  592.           }
  593.         }
  594.         
  595.         free_Mail(&t);
  596.   }
  597.   }
  598.   
  599.   if (strlen(pop_host)) {
  600.   
  601.   /* POP retrieval section */
  602.   
  603.   memset((char*)&pop_addr, 0, sizeof(pop_addr));
  604.   if ((pop_addr.sin_addr.s_addr = inet_addr(pop_host))==-1) {
  605.     hostent = gethostbyname(pop_host);
  606.     if (!hostent) {
  607.       fprintf(stderr, "Unable to resolve POP host '%s'", pop_host);
  608.       goto end;
  609.     }
  610.     memcpy((char*)&pop_addr.sin_addr.s_addr, hostent->h_addr,hostent->h_length);
  611.   }
  612.   pop_addr.sin_family = AF_INET;
  613.   pop_addr.sin_port = htons(110);
  614.   
  615.   if ((popfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  616.     perror("Unable to obtain socket");
  617.     goto end;
  618.   }
  619.   
  620.   if (connect(popfd, (struct sockaddr*)&pop_addr, sizeof(pop_addr))<0) {
  621.     fprintf(stderr, "Unable to connect to POP server '%s'\n", pop_host);
  622.     close(popfd);
  623.     goto end;
  624.   }
  625.  
  626.   read(popfd, buffer, 1024);
  627.   if (buffer[0] != '+') {
  628.     fprintf(stderr, "POP server failed to announce itself\n");
  629.     goto endpop;
  630.   }  
  631.   
  632.   sprintf(buffer, "USER %s\r\n", pop_user);
  633.   write(popfd, buffer, strlen(buffer));
  634.   read(popfd, buffer, 1024);
  635.   if (buffer[0] != '+') {
  636.     fprintf(stderr, "USER command to POP server failed\n");
  637.     goto endpop;
  638.   }
  639.  
  640.   sprintf(buffer, "PASS %s\r\n", pop_pass);
  641.   write(popfd, buffer, strlen(buffer));
  642.   read(popfd, buffer, 1024);
  643.   if (buffer[0] != '+') {
  644.     fprintf(stderr, "PASS command to POP server failed\n");
  645.     close(popfd);
  646.     goto endpop;
  647.   }
  648.   
  649.   for(i=1;1;i++) {
  650.     int len;
  651.     char * msg;
  652.     int h;
  653.     struct Mail t;
  654.     
  655.     t.to = 0;
  656.     t.from = 0;
  657.     t.cc = 0;
  658.     t.bcc = 0;
  659.     t.subject = 0;
  660.     t.replyTo = 0;
  661.     t.sentTo = 0;
  662.     t.body = 0;
  663.     t.dated = 0;
  664.     
  665.     sprintf(buffer, "LIST %d\r\n", i);
  666.     write(popfd, buffer, strlen(buffer));
  667.     l = read(popfd, buffer, 1024);
  668.     if (l<0) {
  669.       perror("Unable to read from socket");
  670.       goto endpop;
  671.     }
  672.     buffer[l] = 0;
  673.     if (buffer[0] != '+')
  674.       break;
  675.     
  676.     sscanf(buffer, "%*s %*d %d", &len);
  677.     
  678.     if (len > 16000) 
  679.       continue; 
  680.  
  681.     sprintf(buffer, "RETR %d\r\n", i);
  682.     write(popfd, buffer, strlen(buffer));
  683.     l = getpopstring(popfd, buffer);
  684.     if ((l < 0) || (buffer[0] != '+')) {
  685.       /* Weird */
  686.       continue;
  687.     } else
  688.       buffer[l] = 0;
  689.     
  690.     msg = buffer;
  691.     h = 1;
  692.     for(;;) {
  693.       if (getpopstring(popfd, msg) < 0) {
  694.         fprintf(stderr, "Error reading message\n");
  695.         goto endpop;
  696.       }
  697.       
  698.       if (h == 1) { /* Header mode */
  699.         if ((msg[0] == '.') && (msg[1] == '\n') && (msg[2] == 0)) {
  700.           break; /* End of message */
  701.         }
  702.  
  703.         if (msg[0] == '\n') {
  704.           h = 0;
  705.           header(&t, 0);
  706.         } else 
  707.           header(&t, msg);
  708.         continue;
  709.       }
  710.       
  711.       if ((msg[0] == '.') && (msg[1] == '\n') && (msg[2] == 0)) {
  712.         msg[0] = 0;
  713.         break; /* End of message */
  714.       }
  715.       
  716.       if (msg[0] == '.') {
  717.         /* Must be escape */
  718.         memmove(msg, msg+1, strlen(msg));
  719.       }
  720.       
  721.       msg += strlen(msg);
  722.     }
  723.     
  724.     /* Well, we've now got the message. I bet _you_ feel happy with yourself. */
  725.     
  726.     if (h) {
  727.       /* Oops, incomplete message, still reading headers */
  728.       fprintf(stderr, "Incomplete message %d\n", i);
  729.       free_Mail(&t);
  730.       continue;
  731.     }
  732.     
  733.     if (strlen(msg) > p.truncate) {
  734.       /* We could truncate it, but we won't for now */
  735.       fprintf(stderr, "Message %d too large (%ld bytes)\n", i, (long)strlen(msg));
  736.       free_Mail(&t);
  737.       continue;
  738.     }
  739.     
  740.     t.body = strdup(buffer);
  741.     
  742.     len = pack_Mail(&t, buffer, 0xffff);
  743.     
  744.     if (dlp_WriteRecord(sd, db, 0, 0, 0, buffer, len, 0)>0) {
  745.       rec++;
  746.       if (strcmp(pop_keep,"delete")==0) { 
  747.         sprintf(buffer, "DELE %d\r\n", i);
  748.         write(popfd, buffer, strlen(buffer));
  749.         read(popfd, buffer, 1024);
  750.         if (buffer[0] != '+') {
  751.           fprintf(stderr, "Error deleting message %d\n", i);
  752.           dupe++;
  753.         }
  754.       } else
  755.         dupe++;
  756.     } else {
  757.       fprintf(stderr,"Error writing message to Pilot\n");
  758.     }
  759.     
  760.     free_Mail(&t);
  761.   }
  762.   
  763.   sprintf(buffer, "QUIT\r\n");
  764.   write(popfd, buffer, strlen(buffer));
  765.   read(popfd, buffer, 1024);
  766.   if (buffer[0] != '+') {
  767.     fprintf(stderr, "QUIT command to POP server failed\n");
  768.   }  
  769.  
  770. endpop:  
  771.   close(popfd);
  772.   
  773.   }
  774.  
  775.   if (strlen(mh_dir)) {
  776.  
  777.       fprintf(stderr, "Reading directory %s... ", mh_dir);
  778.       fflush(stderr);
  779.  
  780.   /* MH directory reading section */
  781.   
  782.   for(i=1;1;i++) {
  783.     int len;
  784.     char * msg;
  785.     int h;
  786.     struct Mail t;
  787.     int mhmsg;
  788.     
  789.     t.to = 0;
  790.     t.from = 0;
  791.     t.cc = 0;
  792.     t.bcc = 0;
  793.     t.subject = 0;
  794.     t.replyTo = 0;
  795.     t.sentTo = 0;
  796.     t.body = 0;
  797.     t.dated = 0;
  798.     
  799.     if((mhmsg=openmhmsg(mh_dir, i))<0) {
  800.         break;
  801.     }
  802.  
  803.     fprintf(stderr, "%d ", i);
  804.     fflush(stderr);
  805.  
  806.     /* Read the message */
  807.     len=0;
  808.     while((len<sizeof(buffer)) && 
  809.           ((l=read(mhmsg, (char*)(buffer+len), (sizeof(buffer)-len)))>0)) {
  810.         len+=l;
  811.     }
  812.     buffer[len]=0;
  813.  
  814.     if(l<0) {
  815.         perror("Error while reading message");
  816.         goto endmh;
  817.     }
  818.  
  819.     msg = buffer;
  820.     h = 1;
  821.     while(h==1) {
  822.       markline(msg);
  823.       
  824.       if ((msg[0] == 0) && (msg[1] == 0)) {
  825.           break; /* End of message */
  826.       }
  827.       
  828.       if (msg[0] == 0) {
  829.           h = 0;
  830.           header(&t, 0);
  831.       } else 
  832.           header(&t, msg);
  833.       msg += strlen(msg)+1;
  834.     }
  835.  
  836.     /* When we get here, we are done with the headers */
  837.     if((*msg)==0) {
  838.         /* Empty message */
  839.         h=1;
  840.     }
  841.  
  842.     /* Well, we've now got the message. I bet _you_ feel happy with yourself. */
  843.     
  844.     if (h) {
  845.       /* Oops, incomplete message, still reading headers */
  846.       fprintf(stderr, "Incomplete message %d\n", i);
  847.       free_Mail(&t);
  848.       continue;
  849.     }
  850.  
  851.     if (strlen(msg) > p.truncate) {
  852.         /* We could truncate it, but we won't for now */
  853.         fprintf(stderr, "Message %d too large (%ld bytes)\n", i, (long)strlen(msg));
  854.         free_Mail(&t);
  855.         continue;
  856.     }
  857.     
  858.     t.body = strdup(msg);
  859.     
  860.     len = pack_Mail(&t, buffer, 0xffff);
  861.     
  862.     if (dlp_WriteRecord(sd, db, 0, 0, 0, buffer, len, 0)>0) {
  863.       rec++;
  864.       if (strcmp(pop_keep,"delete")==0) { 
  865.           char filename[1000];
  866.           sprintf(filename, "%s/%d", mh_dir, i);
  867.           close(mhmsg);
  868.           if(unlink(filename)) {
  869.               fprintf(stderr, "Error deleting message %d\n", i);
  870.               dupe++;
  871.           }
  872.           continue;
  873.       } else
  874.         dupe++;
  875.     } else {
  876.       fprintf(stderr,"Error writing message to Pilot\n");
  877.     }
  878.     
  879.     free_Mail(&t);
  880.  
  881.     close(mhmsg);
  882.   }
  883.   
  884. endmh:  
  885.   fprintf(stderr, "\n");
  886.  
  887.   }
  888.  
  889. end:  
  890.   free_MailSyncPref(&p);
  891.   free_MailSignaturePref(&sig);
  892.   free_MailAppInfo(&tai);
  893.   
  894.   dlp_ResetLastSyncPC(sd);
  895.  
  896.   /* Close the database */
  897.   dlp_CloseDB(sd, db);
  898.  
  899.   sprintf(buffer, "Finished transferring mail. %d message%s sent, %d message%s received.\n",
  900.     sent, (sent == 1) ? "" : "s", rec, (rec == 1) ? "" : "s");
  901.   if (lost || dupe)
  902.     sprintf(buffer+strlen(buffer), "(And %d lost, %d duplicated. Sorry.)\n", lost, dupe);
  903.   fprintf(stderr, buffer);  
  904.   dlp_AddSyncLogEntry(sd, buffer);
  905.  
  906.   pi_close(sd);
  907.   exit(0);
  908. }
  909.  
  910.